package com.sbtr.business.calibration.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sbtr.business.calibration.entity.Calibration;
import com.sbtr.business.calibration.entity.CalibrationRecordDaily;
import com.sbtr.business.calibration.entity.CalibrationTxt;
import com.sbtr.business.calibration.mapper.CalibrationTxtMapper;
import com.sbtr.business.calibration.service.ICalibrationService;
import com.sbtr.business.calibration.service.ICalibrationTxtService;
import com.sbtr.common.PageDto;
import com.sbtr.constant.ColumnConstant;
import com.sbtr.open.calibration.dto.*;
import com.sbtr.util.BeanCopyUtils;
import com.sbtr.util.PageDtoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.Executor;


/**
 * <p>
 * 标定集 服务实现类
 * </p>
 */
@Transactional
@Service
public class CalibrationServiceTxtImpl extends ServiceImpl<CalibrationTxtMapper, CalibrationTxt>
        implements ICalibrationTxtService {

    private static final Logger logger = LoggerFactory.getLogger(CalibrationServiceTxtImpl.class);
    @Resource(name = "asyncTxtExecutor")
    Executor asyncExecutor;
    @Autowired
    @Lazy
    private ICalibrationService calibrationApi;
    @Autowired
    private CalibrationRecordDailyServiceImpl calibrationRecordDailyService;

    @Override
    public CalibrationDto save(CalibrationDto dto) {
        Calibration data = BeanCopyUtils.copyProperties(dto, Calibration.class);
        if (dto.getId() == null) {
//			save(data);
            dto.setId(data.getId());
        } else {
            return BeanCopyUtils.copyProperties(data, CalibrationDto.class);
        }
        return dto;
    }

    @Override
    public Boolean update(CalibrationTxtDto dto) {
        CalibrationTxt calibrationTxt = BeanCopyUtils.copyProperties(dto, CalibrationTxt.class);
        calibrationTxt.setId(dto.getId());
        return updateById(calibrationTxt);
    }

    @Override
    public boolean batchSave(List<CalibrationTxtDto> dtos) {
        List<CalibrationTxt> materialtxt = BeanCopyUtils.copyProperties(dtos, CalibrationTxt.class);
        if (materialtxt.size() < 10000) {
            saveBatch(materialtxt);
        } else {
            int num = 2000;
            int k = 0;
            List<CalibrationTxt> saveList = new ArrayList<>();
            ;
            for (int i = 0; i < materialtxt.size(); i++) {
                k++;
                saveList.add(materialtxt.get(i));
                if (k == num || i - 1 == materialtxt.size()) {
                    k = 0;
                    batchSaveAsync(saveList);
                    saveList = new ArrayList<>();
                }
            }
        }
        return true;
    }

    @Override
    public List<CalibrationTxtDto> search(Long calibrationId) {
        QueryWrapper<CalibrationTxt> wrapper = new QueryWrapper<>();
        wrapper.eq("calibration_id", calibrationId).orderByDesc("id");
        return BeanCopyUtils.copyProperties(list(wrapper), CalibrationTxtDto.class);
    }

//	@RequestMapping(value = "/count-txt-by-material", method = RequestMethod.POST)
//	public List<MaterialSetDto> countPicByMaterialSetId(@RequestBody List<Long> materialSetIds) {
//		return baseMapper.countTxtByMaterialSetId(materialSetIds);
//	}

    @Override
    public PageDto<CalibrationTxtDto> searchTxt(String materialSetId, Long currPage, Long pageSize) {

        QueryWrapper<CalibrationTxt> wrapper = new QueryWrapper<>();
        IPage<CalibrationTxt> page = new Page<>();
        if (currPage != null && currPage < 1) {
            page.setCurrent(1);
        }
        if (pageSize != null && pageSize < 1) {
            page.setSize(10);
        }
        wrapper.eq("material_set_id", materialSetId).eq("is_available", 1).orderByDesc("create_time").orderByDesc("id");
        page = page(page, wrapper);
        page.setPages(currPage);
        page.setSize(pageSize);
        PageDto<CalibrationTxtDto> pageDto = PageDtoUtils.getPageDtoByIPage(page, CalibrationTxtDto.class);

        return pageDto;
    }

//	@RequestMapping(value = "/searchTxts", method = RequestMethod.GET)
//	public PageDto<CalibrationTxtDto> searchTxtsNoMark(@RequestParam("materialSetId") String materialSetId,
//													@RequestParam("page") Long currPage, @RequestParam("pageSize") Long pageSize) {
//
//		if(currPage < 1){
//			currPage = 0L;
//		}
//		if(pageSize < 1){
//			pageSize = 0L;
//		}
//
//		PageDto<CalibrationTxtDto> pageDto = new PageDto<>();
//
//		try {
//			List<CalibrationTxtDto> materialTxtDtoList =calibrationTxtMapper.searchNotNotedTxt(Long.parseLong(materialSetId), (currPage-1)*pageSize, pageSize);
//			int count = calibrationTxtMapper.searchNotNotedTxtCount(Long.parseLong(materialSetId));
//			pageDto.setRowCount(count);
//			pageDto.setList(materialTxtDtoList);
//		} catch (NumberFormatException e) {
//			log.error(e.toString());
//		}
//		return pageDto;
//	}

    @Override
    public List<CalibrationTxtDto> searchByIds(List<Long> idList) {
        QueryWrapper<CalibrationTxt> wrapper = new QueryWrapper<>();
        wrapper.in("id", idList);
        wrapper.eq("is_available", 1);
        List<CalibrationTxt> txt = list(wrapper);
        return BeanCopyUtils.copyProperties(txt, CalibrationTxtDto.class);
    }

    @Override
    public List<CalibrationTxtDto> searchHasCalibratedByIds(Long id) {

        CalibrationDto calibrationDto = calibrationApi.findById(id);
        if (calibrationDto.getAvailable()) {
            QueryWrapper<CalibrationTxt> wrapper = new QueryWrapper<>();
            wrapper.in("calibration_id", id);
            wrapper.eq("completed", "1");
            List<CalibrationTxt> txt = list(wrapper);
            return BeanCopyUtils.copyProperties(txt, CalibrationTxtDto.class);
        }
        return null;
    }

    @Override
    public List<CalibrationTxtDto> searchHasCalibratedByIdsAndFinisher(Long id, String finisher
    ) {

        CalibrationDto calibrationDto = calibrationApi.findById(id);
        if (calibrationDto.getAvailable()) {
            QueryWrapper<CalibrationTxt> wrapper = new QueryWrapper<>();
            wrapper.in("calibration_id", id);
            wrapper.eq("finisher", finisher);
            wrapper.eq("completed", "1");
            List<CalibrationTxt> txt = list(wrapper);
            return BeanCopyUtils.copyProperties(txt, CalibrationTxtDto.class);
        }
        return null;
    }

    @Override
    public boolean batchDeleteTxt(List<Long> idList) {
        boolean b1 = this.logicBatchDelete(idList);
//		boolean b2 = calibrationApi.detailBatchDeleteTxt(idList);
//		return b1 && b2;
        return false;
    }


    /**
     * 逻辑删除素材文本记录(修改状态为0)
     *
     * @param idList
     * @return
     */
    private boolean logicBatchDelete(List<Long> idList) {
        UpdateWrapper<CalibrationTxt> wrapper = new UpdateWrapper<>();
        wrapper.set("is_available", 0);
        wrapper.in("id", idList);
        return this.update(wrapper);
    }

    @Override
    public List<CalibrationCountDto> countByCalibrationSetId(List<Long> calibrationIds) {
        return baseMapper.countByCalibrationSetId(calibrationIds);
    }

    @Override
    public PageDto<CalibrationTxtDto> getTxtNoDetails(CalibrationSearchByDetailsDto dto) {

        IPage<CalibrationTxt> page = new Page<>();
        page.setSize(dto.getPageSize());
        page.setCurrent(dto.getPage());
        QueryWrapper<CalibrationTxt> wrapper = new QueryWrapper<>();

        if (null != dto.getId()) {
            wrapper.eq("calibration_id", dto.getId());
        }
        if (null != dto.getFinisher()) {
            wrapper.eq("finisher", dto.getFinisher());
        }
        wrapper.eq("completed", "0");
//		wrapper.orderByDesc("id");
        page = page(page, wrapper);
        PageDto<CalibrationTxtDto> pageDto = PageDtoUtils.getPageDtoByIPage(page, CalibrationTxtDto.class);
        return pageDto;
    }

    @Override
    public PageDto<CalibrationTxtDto> getTxtDetails(CalibrationSearchByDetailsDto dto) {
        IPage<CalibrationTxt> page = new Page<>();
        page.setSize(dto.getPageSize());
        page.setCurrent(dto.getPage());
        QueryWrapper<CalibrationTxt> wrapper = new QueryWrapper<>();

        if (null != dto.getId()) {
            wrapper.eq("calibration_id", dto.getId());
        }
        if (null != dto.getFinisher()) {
            wrapper.eq("finisher", dto.getFinisher());
        }
        if (null != dto.getClassifyId()) {
            wrapper.eq("classify_id", dto.getClassifyId());
        }

        wrapper.eq("completed", "1");
//		wrapper.orderByDesc("id");
        page = page(page, wrapper);
        PageDto<CalibrationTxtDto> pageDto = PageDtoUtils.getPageDtoByIPage(page, CalibrationTxtDto.class);
        return pageDto;
    }

    @Override
    public List<CalibrationCountByClassifyDto> countHasCalibrated(CalibrationSearchByDetailsDto dto) {
        String finisher = dto.getFinisher();
        Long calibration_id = dto.getId();
        Long classify_id = dto.getClassifyId();

        List<CalibrationCountByClassifyDto> dtoList = baseMapper.countHasCalibrated(finisher, calibration_id, classify_id);
        return dtoList;
    }

    @Override
    public boolean updateCalibrationTxtRecordDaily(CalibrationDetailsDto calibrationDetails) {
        QueryWrapper<CalibrationTxt> wrapper = new QueryWrapper<>();
        long calibrationId = calibrationDetails.getCalibrationId();
        String finisher = calibrationDetails.getFinisher();
        wrapper.eq("calibration_id", calibrationId);
        wrapper.eq("finisher", finisher);
//		Integer totalCount = count(wrapper);
        wrapper.eq("completed", "1");
        Calendar calendar = new GregorianCalendar();
        //        Calendar calendar = Calendar.getInstance();//日历对象
        calendar.setTime(new Date());//当天时间赋给日历对象
        calendar.set(Calendar.HOUR_OF_DAY, 0);//设置对象日历格式
        calendar.set(Calendar.MINUTE, 0);//设置为当天零点
        calendar.set(Calendar.SECOND, 0);
        Date updateTimeFrom = calendar.getTime();//再返回时间对象
        calendar.add(Calendar.DAY_OF_MONTH, 1);//把日期往后增加一天,整数  往后推,负数往前移动
        Date updateTimeTo = calendar.getTime();//返回另一个时间对象
        wrapper.between(ColumnConstant.UPDATE_TIME, updateTimeFrom, updateTimeTo);
        Integer completeCount = count(wrapper);
        CalibrationRecordDaily calibrationRecordDaily = calibrationRecordDailyService.findByCalibrationIdFinisher(calibrationId, finisher);
        if (null == calibrationRecordDaily) {
            calibrationRecordDaily = new CalibrationRecordDaily();
            calibrationRecordDaily.setCalibrationId(calibrationId);
            calibrationRecordDaily.setFinisher(finisher);
            calibrationRecordDaily.setCalibrationDetailId(calibrationDetails.getId());
            calibrationRecordDaily.setUpdateTime(new Date());
            calibrationRecordDaily.setCompletedCount(completeCount);
        } else {
            calibrationRecordDaily.setUpdateTime(new Date());
            calibrationRecordDaily.setCompletedCount(completeCount);
        }
        return calibrationRecordDailyService.saveOrUpdate(calibrationRecordDaily);
    }


//	@RequestMapping(value = "/count-by-calibration", method = RequestMethod.POST)
//	public List<CalibrationCountDto> countByCalibrationSetId(@RequestBody List<Long> calibrationSetIds) {
//		return baseMapper.countByCalibrationSetId(calibrationSetIds);
//	}

    @Override
    public List<CalibrationCountByFinisherDto> countTaskByCalibrationIds(Long id) {
        return baseMapper.countTaskByCalibrationIds(id);
    }


    @Async("asyncTxtExecutor")
    public void batchSaveAsync(List<CalibrationTxt> materialTxtList) {
        asyncExecutor.execute(new batchSaveThread(materialTxtList));
    }

    @Async
    class batchSaveThread implements Runnable {

        private List<CalibrationTxt> materialTxtList;

        public batchSaveThread(List<CalibrationTxt> list) {
            this.materialTxtList = list;
        }

        @Override
        public void run() {
            saveBatch(materialTxtList);
        }
    }
}